package com.example.web;

import com.example.vo.Result;
import com.example.vo.UserVo;
import com.example.config.security.JWTAuthenticationManager;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.Objects;

@RestController
@RequestMapping("auth")
public class AuthController extends BaseController {

    @Autowired
    UserService userService;

    @Autowired
    JWTAuthenticationManager jwtAuthenticationManager;

    @GetMapping(value = "/login")
    public Mono<Result> login(UserVo userVo) {
        return authenticate(userVo);
    }

    @PostMapping(value = "/login")
    public Mono<Result> postLogin(@RequestBody UserVo userVo) {
        return authenticate(userVo);
    }

    private Mono<Result> authenticate(UserVo userVo) {
        return Mono.just(userVo)
                .filter(Objects::nonNull)
                .map(loginVo -> this.jwtAuthenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword())))
                .flatMap(authenticationMono -> authenticationMono)
                .subscribeOn(Schedulers.elastic())
                .doOnSuccess(ReactiveSecurityContextHolder::withAuthentication)
                .map(authentication -> userService.login(authentication))
                .flatMap(userVoMono -> userVoMono)
                .map(respUserVo -> Result.success("登录成功！", respUserVo))
                .switchIfEmpty(Mono.error(new UsernameNotFoundException("Bad request")));
    }
}
